#pragma once
#include <iostream>
#include <string>
#include "logger.hpp"
#include <mysql/mysql.h>
#include <jsoncpp/json/json.h>
#include <sstream>
#include <memory>
#include<vector>
#include<fstream>
#include<websocketpp/server.hpp>
#include<websocketpp/config/asio_no_tls.hpp>
#include<unordered_map>
typedef websocketpp::server<websocketpp::config::asio> websocket_server;
class mysql_util
{
public:
    static MYSQL *mysql_create(const std::string &host,
                               const std::string &username,
                               const std::string &passwd,
                               const std::string &dbname,
                               uint16_t port = 3306)
    {
        MYSQL *mysql = mysql_init(nullptr);
        if (mysql == nullptr)
        {
            ERROR_LOG("初始化数据库失败");
            return nullptr;
        }
        if (mysql_real_connect(mysql, host.c_str(), username.c_str(), passwd.c_str(), dbname.c_str(), port, nullptr, 0) == nullptr)
        {
            ERROR_LOG("连接数据库失败");
            return nullptr;
        }
        int ret = mysql_set_character_set(mysql, "utf8");
        if (ret != 0)
        {
            ERROR_LOG("设置字符集失败");
            return nullptr;
        }
        return mysql;
    }
    static bool mysql_exec(MYSQL *mysql, const std::string &sql)
    {
        if (mysql_query(mysql, sql.c_str()) != 0)
        {
            INFO_LOG("执行数据库语句:%s失败,失败原因:%s\n", sql.c_str(),mysql_error(mysql));
            //mysql_close(mysql);
            return false;
        }
        return true;
    }
    static void mysql_destory(MYSQL *mysql)
    {
        if (mysql != nullptr)
            mysql_close(mysql);
    }
};

class json_util
{
public:
    static bool Serialize(const Json::Value &val, std::string &str)
    {
        Json::StreamWriterBuilder writebuild;
        writebuild["emitUTF8"] = true;
        static std::unique_ptr<Json::StreamWriter> writer(writebuild.newStreamWriter());
        std::stringstream os;
        int ret = writer->write(val, &os);
        if (ret != 0)
        {
            ERROR_LOG("序列化失败");
            return false;
        }
        str = os.str();
        return true;
    }
    static bool UnSerialize(Json::Value &val, const std::string &str)
    {
        Json::CharReaderBuilder charreader;
        static std::unique_ptr<Json::CharReader> reader(charreader.newCharReader());
        char buffer[1024] = {0};
        bool ret = reader->parse(&str[0], &str[0] + str.size(), &val, nullptr);
        if (ret != true)
        {
            ERROR_LOG("反序列化失败");
            return false;
        }
        return true;
    }
};

class string_util
{
    public:
    static int split(const std::string& src,const std::string& sep,std::vector<std::string>& res)
    {
        size_t pos=0,idx=0;
        while(idx<src.size())
        {
            pos=src.find(sep,idx);
            if(pos==std::string::npos)
            {
                res.push_back(src.substr(idx));
                break;
            }
            if(idx==pos)
            {
                idx+=sep.size();
                continue;
            }
            res.push_back(src.substr(idx,pos-idx));
            idx=pos+sep.size();
        }
        return res.size();
    }
};

class file_util
{
    public:
    static bool read(const std::string& filename,std::string& body)
    {
        std::ifstream ifs(filename,std::ios::binary);
        if(ifs.is_open()==false)
        {
            ERROR_LOG("打开文件:%s 失败",filename.c_str());
            return false;
        }
        size_t fsize=0;
        ifs.seekg(0,std::ios::end);
        fsize=ifs.tellg();
        ifs.seekg(0,std::ios::beg);
        body.resize(fsize);
        ifs.read(&body[0],fsize);
        if(ifs.good()==false)//判断上次操作是否是ok的
        {
            ERROR_LOG("读取文件%s失败",filename.c_str());
            ifs.close();
            return false;  
        }
        ifs.close();
        return true;
    }
};